package main

import (
	"context"
	"database/sql"
	"encoding/json"
	"github.com/gorilla/websocket"
	"github.com/redis/go-redis/v9"
	"golang.org/x/crypto/bcrypt"
	"log"
	"net"
	"net/http"
	"path"
	"real-time-communication/utils"
	"runtime"
	"strconv"
)

var Ctx = context.Background()

var Rdb = InitRedis()

var BASE_URL string

var SERVER_IP = "http://192.168.192.195:7888"

// 映射服务器静态资源(头像映射)
func init() {
	_, fullFilename, _, _ := runtime.Caller(0)
	BASE_URL = path.Dir(fullFilename) + "/upload/avatar"
}

func main() {
	log.Println("正在启动服务器")

	fs := http.FileServer(http.Dir(BASE_URL))
	http.HandleFunc("/avatar/", func(w http.ResponseWriter, r *http.Request) {
		// 设置跨域请求头
		w.Header().Set("Access-Control-Allow-Origin", "*")

		// 将请求转发到实际的文件服务器
		http.StripPrefix("/avatar/", fs).ServeHTTP(w, r)
	})

	http.HandleFunc("/ws", handleWebSocketConn)

	// user-api
	http.HandleFunc("/login", login)

	http.HandleFunc("/register", register)

	http.HandleFunc("/user/queryUserNickname", queryUserNickname)

	http.HandleFunc("/user/checkUsername", checkUsername)

	http.HandleFunc("/user/forgetPassword", forgetPassword)

	http.HandleFunc("/user/modifyPassword", modifyPassword)

	http.HandleFunc("/user/profile", queryUserProfile)

	http.HandleFunc("/user/upload/avatar", uploadAvatar)

	http.HandleFunc("/user/modify", modifyUserProfile)

	// friend-api
	http.HandleFunc("/friend/getFriendList", getFriendList)

	http.HandleFunc("/friend/getFriendApplyList", getFriendApplyList)

	http.HandleFunc("/friend/queryFriendView", queryFriendView)

	http.HandleFunc("/friend/searchFriend", searchFriend)

	http.HandleFunc("/friend/checkIsFriend", checkIsFriend)

	http.HandleFunc("/friend/deleteFriend", deleteFriend)

	// message-api
	http.HandleFunc("/message/queryChatHistory", queryChatHistory)

	http.HandleFunc("/message/getUserResentMessage", getUserResentMessage)

	// cache-api
	http.HandleFunc("/cache/refreshLastRead", refreshLastRead)

	http.HandleFunc("/cache/getUserFriendApplyRecord", getUserFriendApplyRecord)

	http.HandleFunc("/cache/refreshFriendApply", refreshFriendApply)

	// p2p-call-api
	http.HandleFunc("/p2p/call/record", saveP2PCallRecord)

	if err := http.ListenAndServe(":7888", nil); err != nil {
		log.Fatalln("服务器启动失败:", err)
		return
	}
}

var clients = make(map[int]*Client)

// 登录验证成功以后，连接 webSocket，更新用户的登录IP和登录时间，为用户提供一个客户端
func handleWebSocketConn(w http.ResponseWriter, r *http.Request) {

	// 将 Http升级为 Websocket
	upgrader := websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		http.Error(w, "服务端异常", http.StatusInternalServerError)
		log.Fatal("Failed to upgrade connection to WebSocket:", err)
		return
	}

	db, err := sql.Open("sqlite3", "./RealTimeCommunication.db")
	if err != nil {
		http.Error(w, "服务端异常", http.StatusInternalServerError)
		log.Fatal("数据库异常", err)
		return
	}
	defer db.Close()

	// 这里获取的是用户id
	userId := r.URL.Query().Get("userId")

	// 更新登录时间和登录IP
	ip, port, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		http.Error(w, "获取客户端IP地址失败", http.StatusBadRequest)
		log.Fatal("获取客户端IP地址失败", err)
		return
	} else {
		stat, err := db.Prepare("UPDATE user SET login_ip = ?, login_time = DATETIME('now') WHERE user_id = ?")
		if err != nil {
			http.Error(w, "服务端异常", http.StatusInternalServerError)
			log.Fatal("数据库异常", err)
			return
		}
		defer stat.Close()

		_, err = stat.Exec(ip, userId)
		if err != nil {
			http.Error(w, "服务端异常", http.StatusInternalServerError)
			log.Fatal("数据库异常", err)
			return
		}
	}

	log.Println("有新的连接进入WebSocket服务器:", ip)

	var user User
	// 获取用户全部数据给到客户端
	selectSQL := `SELECT * FROM user WHERE user_id = ?`
	row := db.QueryRow(selectSQL, userId)
	err = row.Scan(&user.UserId, &user.Username, &user.Password, &user.Email, &user.Nickname, &user.Avatar, &user.LoginIp, &user.LoginTime)
	if err == sql.ErrNoRows {
		http.Error(w, "用户不存在", http.StatusBadRequest)
	} else if err != nil && err != sql.ErrNoRows {
		http.Error(w, "服务端异常", http.StatusInternalServerError)
		log.Fatal("数据库异常", err)
		return
	}

	if isContain, err := utils.ContainKey(clients, user.UserId); err != nil {
		http.Error(w, "服务端异常", http.StatusInternalServerError)
		log.Fatal(err)
		return
	} else if isContain && err == nil {
		var socketMsg WebSocketMsg
		socketMsg.SendType = logout
		res, err := json.Marshal(socketMsg)
		if err != nil {
			log.Fatal("Json编码失败:", err)
		}

		err = clients[user.UserId].Conn.WriteMessage(websocket.TextMessage, res)
		if err != nil {
			log.Fatal("转发错误:", err)
		}
		//clients[user.UserId].LogoutClient()
		delete(clients, user.UserId)
	}

	client := NewClient(ip, port, &user, conn)
	clients[user.UserId] = client

	go client.ListenNewMessage()
}

// 登录
func login(w http.ResponseWriter, r *http.Request) {

	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	var user User
	err := json.NewDecoder(r.Body).Decode(&user)
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}

	username := user.Username
	password := user.Password

	if utils.IsEmpty(username, password) {
		res, err := json.Marshal(utils.ErrorWithMsg("帐号或密码为空"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	db, err := sql.Open("sqlite3", "./RealTimeCommunication.db")
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatalln("数据库开启异常:", err)
		return
	}
	defer db.Close()

	selectSQL := `SELECT user_id, username, password, nickname, avatar FROM user WHERE username = ?`
	row := db.QueryRow(selectSQL, username)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatalln("数据库异常:", err)
		return
	}

	err = row.Scan(&user.UserId, &user.Username, &user.Password, &user.Nickname, &user.Avatar)
	if err == sql.ErrNoRows {
		res, err := json.Marshal(utils.ErrorWithMsg("帐号或密码错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	} else if err != nil && err != sql.ErrNoRows {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatalln("数据库异常:", err)
		return
	}

	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("帐号或密码错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	res, err := json.Marshal(utils.SuccessWithMsgAndData("登录成功", user))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 注册
func register(w http.ResponseWriter, r *http.Request) {

	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	var user User
	err := json.NewDecoder(r.Body).Decode(&user)
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}

	username := user.Username
	password := user.Password
	email := user.Email

	if utils.IsEmpty(username, password, email) {
		res, err := json.Marshal(utils.ErrorWithMsg("表单内容为空"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	if !utils.IsStrValid(username, "^[a-zA-z][0-9]{9,19}$") {
		res, err := json.Marshal(utils.ErrorWithMsg("帐号格式不规范"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	if !utils.IsStrValid(password, "^[A-Za-z0-9]{6,15}$") ||
		!utils.IsStrValid(password, "[A-Z]") ||
		!utils.IsStrValid(password, "[0-9]") {
		res, err := json.Marshal(utils.ErrorWithMsg("密码格式不规范"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	if !utils.IsStrValid(email, "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$") {
		res, err := json.Marshal(utils.ErrorWithMsg("邮箱格式不规范"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	db, err := sql.Open("sqlite3", "./RealTimeCommunication.db")
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatalln("数据库开启异常:", err)
		return
	}
	defer db.Close()

	selectSQL := `SELECT * FROM user WHERE username = ?`
	row := db.QueryRow(selectSQL, username)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatalln("数据库异常:", err)
		return
	}

	var selectUser User
	err = row.Scan(&selectUser.UserId, &selectUser.Username, &selectUser.Password, &selectUser.Email,
		&selectUser.Nickname, &selectUser.Avatar, &selectUser.LoginIp, &selectUser.LoginTime)
	if err != sql.ErrNoRows {
		res, err := json.Marshal(utils.ErrorWithMsg("帐号已存在"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	} else if err != nil && err != sql.ErrNoRows {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatalln("数据库异常:", err)
		return
	}

	// 密码加密
	hashPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatal("创建哈希密码失败", err)
		return
	}

	insertSQL := `INSERT INTO User (username, password, email, nickname, avatar) VALUES (?, ?, ?, ?, ?)`
	_, err = db.Exec(insertSQL, username, string(hashPassword), email, "用户"+username, SERVER_IP+"/avatar/defaultAvatar.png")
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatalln("数据库异常:", err)
		return
	}
	res, err := json.Marshal(utils.SuccessWithMsgAndData("注册成功", user.UserId))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 获取好友列表
func getFriendList(w http.ResponseWriter, r *http.Request) {

	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	userIdParam := r.URL.Query().Get("userId")
	searchContent := r.URL.Query().Get("searchContent")

	if utils.IsObjNil(&userIdParam) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	userId, err := strconv.Atoi(userIdParam)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	friendList := GetFriendList(userId, searchContent)
	res, err := json.Marshal(utils.SuccessWithData(friendList))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 获取好友申请列表
func getFriendApplyList(w http.ResponseWriter, r *http.Request) {

	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	param := r.URL.Query().Get("userId")
	if utils.IsObjNil(&param) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	userId, err := strconv.Atoi(param)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	friendList := GetFriendApplyList(userId)
	res, err := json.Marshal(utils.SuccessWithData(friendList))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 通过好友ID获取昵称和头像
func queryFriendView(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	param := r.URL.Query().Get("userId")
	if utils.IsObjNil(&param) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	userId, err := strconv.Atoi(param)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	user := QueryUserAvatarAndNickname(userId)
	res, err := json.Marshal(utils.SuccessWithData(user))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 搜索用户(好友)
func searchFriend(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	params := r.URL.Query()
	if utils.IsObjNil(&params) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	account := params.Get("account")
	userIdParam := params.Get("userId")

	userId, err := strconv.Atoi(userIdParam)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	searchResult := SearchFriend(account, userId)
	res, err := json.Marshal(utils.SuccessWithData(searchResult))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 获取聊天记录
func queryChatHistory(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	params := r.URL.Query()
	if utils.IsObjNil(&params) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	userIdParam := params.Get("userId")
	targetIdParam := params.Get("targetId")

	userId, err := strconv.Atoi(userIdParam)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	targetId, err := strconv.Atoi(targetIdParam)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	result := QueryChatMessage(userId, targetId)
	res, err := json.Marshal(utils.SuccessWithData(result))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return

}

// 获取用户昵称
func queryUserNickname(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	userIdParam := r.URL.Query().Get("userId")
	if utils.IsObjNil(&userIdParam) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	userId, err := strconv.Atoi(userIdParam)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	result := QueryUserNicknameById(userId)
	res, err := json.Marshal(utils.SuccessWithData(result))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return

}

// 获取最近聊天信息
func getUserResentMessage(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	userIdParam := r.URL.Query().Get("userId")
	searchContent := r.URL.Query().Get("searchContent")

	if utils.IsObjNil(&userIdParam) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	userId, err := strconv.Atoi(userIdParam)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	result := QueryResentMessage(userId, searchContent)
	res, err := json.Marshal(utils.SuccessWithData(result))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return

}

// 更新redis
func refreshLastRead(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	var lastRead LastReadKey
	err := json.NewDecoder(r.Body).Decode(&lastRead)
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}

	redisKey := "LastRead:" + strconv.Itoa(lastRead.UserId) + ":" + lastRead.MsgId
	err = Rdb.Set(Ctx, redisKey, lastRead.Id, 0).Err() // 永远不过期

	res, err := json.Marshal(utils.SuccessWithMsg("更新lastRead成功"))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

func getUserFriendApplyRecord(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	userIdParam := r.URL.Query().Get("userId")

	if utils.IsObjNil(&userIdParam) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	redisKey := "FriendApply:" + userIdParam
	result, err := Rdb.Get(Ctx, redisKey).Result()

	if err != redis.Nil {
		res, err := strconv.ParseInt(result, 10, 64)
		if err == nil && res == 1 {
			res, err := json.Marshal(utils.SuccessWithData(true))
			if err != nil {
				log.Fatalln("Json编码异常:", err)
				return
			}
			w.Write(res)
			return
		} else {
			res, err := json.Marshal(utils.SuccessWithData(false))
			if err != nil {
				log.Fatalln("Json编码异常:", err)
				return
			}
			w.Write(res)
			return
		}
	} else {
		res, err := json.Marshal(utils.SuccessWithData(false))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

}

func refreshFriendApply(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	var user LastReadKey
	err := json.NewDecoder(r.Body).Decode(&user)
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}

	redisKey := "FriendApply:" + strconv.Itoa(user.UserId)
	err = Rdb.Set(Ctx, redisKey, 0, 0).Err() // 永远不过期

	res, err := json.Marshal(utils.SuccessWithMsg("更新lastRead成功"))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 验证帐号(用于忘记密码)
func checkUsername(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	usernameParam := r.URL.Query().Get("username")
	emailParam := r.URL.Query().Get("email")

	if utils.IsObjNil(&usernameParam) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	if utils.IsObjNil(&emailParam) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	db, err := sql.Open("sqlite3", "./RealTimeCommunication.db")
	if err != nil {
		log.Fatal("数据库打开失败:", err)
		return
	}
	defer db.Close()

	var res int
	querySql := "SELECT COUNT(*) > 0 FROM user WHERE username = ? AND email = ?"
	row := db.QueryRow(querySql, usernameParam, emailParam).Scan(&res)
	if row != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("该帐号/邮箱不存在"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	if res > 0 {
		res, err := json.Marshal(utils.SuccessWithMsg("成功"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
	} else {
		res, err := json.Marshal(utils.ErrorWithMsg("该帐号/邮箱不存在"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
	}

	return
}

// 忘记密码(在修改密码的基础上，调用一层用户校验)
func forgetPassword(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPut {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	var form ForgetPassword
	err := json.NewDecoder(r.Body).Decode(&form)
	if err != nil {
		log.Fatalln("Json解码异常:", err)
		return
	}

	if !utils.IsStrValid(form.Password, "^[A-Za-z0-9]{6,15}$") ||
		!utils.IsStrValid(form.Password, "[A-Z]") ||
		!utils.IsStrValid(form.Password, "[0-9]") {
		res, err := json.Marshal(utils.ErrorWithMsg("密码格式不规范"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	db, err := sql.Open("sqlite3", "./RealTimeCommunication.db")
	if err != nil {
		log.Fatal("数据库打开失败:", err)
		return
	}
	defer db.Close()

	hashPassword, err := bcrypt.GenerateFromPassword([]byte(form.Password), bcrypt.DefaultCost)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatal("创建哈希密码失败", err)
		return
	}

	modify := "UPDATE user SET password = ? WHERE username = ?"
	_, err = db.Exec(modify, hashPassword, form.Username)

	if err != nil {
		log.Println("数据库异常", err)
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		log.Fatal("创建哈希密码失败", err)
		return
	}

	res, err := json.Marshal(utils.SuccessWithMsg("修改成功"))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 修改密码
func modifyPassword(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPut {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	var modify ModifyPassword
	err := json.NewDecoder(r.Body).Decode(&modify)

	if err != nil {
		log.Fatalln("Json解码异常:", err)
		return
	}

	if utils.IsEmpty(modify.OldPwd, modify.NewPwd) {
		res, err := json.Marshal(utils.ErrorWithMsg("密码不能为空"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	if modify.NewPwd == modify.OldPwd {
		res, err := json.Marshal(utils.ErrorWithMsg("原始密码和新密码不能一样"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	passwordHash := QueryUserPasswordHash(modify.UserId)
	err = bcrypt.CompareHashAndPassword([]byte(passwordHash), []byte(modify.OldPwd))
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("原始密码不正确"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	if !utils.IsStrValid(modify.NewPwd, "^[A-Za-z0-9]{6,15}$") ||
		!utils.IsStrValid(modify.NewPwd, "[A-Z]") ||
		!utils.IsStrValid(modify.NewPwd, "[0-9]") {
		res, err := json.Marshal(utils.ErrorWithMsg("密码格式不规范"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	if ModifyUserPassword(modify) {
		res, err := json.Marshal(utils.SuccessWithMsg("密码已修改"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	} else {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}
}

// 获取当前用户的资料信息（头像、昵称）
func queryUserProfile(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	userIdParams := r.URL.Query().Get("userId")

	if utils.IsObjNil(&userIdParams) {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	userId, err := strconv.Atoi(userIdParams)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	result := QueryUserProfileByUserId(userId)
	res, err := json.Marshal(utils.SuccessWithData(result))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 上传头像业务
func uploadAvatar(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// 限制文件大小30MB
	const limitFileSize = 30 << 20

	// 防止自动保存在内存和磁盘
	r.ParseMultipartForm(0)

	file, header, err := r.FormFile("avatar")
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("文件处理异常，请重新上传"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}
	defer file.Close()

	fileSize := header.Size

	if fileSize > limitFileSize {
		res, err := json.Marshal(utils.ErrorWithMsg("文件大小不能超过30MB"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
		return
	}

	res, err := json.Marshal(UploadAvatar(file, header))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 修改用户信息
func modifyUserProfile(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPut {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	var user User
	err := json.NewDecoder(r.Body).Decode(&user)

	if err != nil {
		log.Fatalln("Json解码异常:", err)
		return
	}

	res, err := json.Marshal(ModifyUser(user))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}

// 检测对方是否为用户的好友
func checkIsFriend(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	params := r.URL.Query()

	userIdParam := params.Get("userId")
	targetIdParams := params.Get("targetId")

	userId, err := strconv.Atoi(userIdParam)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	targetId, err := strconv.Atoi(targetIdParams)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	res, err := json.Marshal(utils.SuccessWithData(CheckIsFriend(userId, targetId)))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return

}

// 删除好友
func deleteFriend(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodDelete {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	params := r.URL.Query()

	userIdParam := params.Get("userId")
	targetIdParams := params.Get("targetId")

	log.Println("接收到数据:", params)

	userId, err := strconv.Atoi(userIdParam)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	targetId, err := strconv.Atoi(targetIdParams)
	if err != nil {
		res, err := json.Marshal(utils.ErrorWithMsg("客户端传值错误"))
		if err != nil {
			log.Fatalln("类型转换失败:", err)
			return
		}
		w.Write(res)
		return
	}

	deleteFriendVo := DeleteFriendVo{
		UserId:   userId,
		TargetId: targetId,
	}

	res := DeleteFriend(deleteFriendVo)

	if res {
		res, err := json.Marshal(utils.SuccessWithMsg("删除成功"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
	} else {
		res, err := json.Marshal(utils.ErrorWithMsg("服务端异常"))
		if err != nil {
			log.Fatalln("Json编码异常:", err)
			return
		}
		w.Write(res)
	}

	return
}

// 记录通话记录
func saveP2PCallRecord(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	var call P2PCall
	err := json.NewDecoder(r.Body).Decode(&call)

	if err != nil {
		log.Fatal("JSON解码异常:", err)
		return
	}

	RecordCall(call)

	res, err := json.Marshal(utils.SuccessWithMsg("记录成功"))
	if err != nil {
		log.Fatalln("Json编码异常:", err)
		return
	}
	w.Write(res)
	return
}
